#!/usr/bin/env python
# coding=utf-8
from google.appengine.ext.webapp import RequestHandler, util

import language
from model.model import Member
from api.myoauth import *
from google.appengine.api import memcache
from google.appengine.ext import webapp
from model import get_member_by_access_token
from v2ex.babel.security import get_current_member
from google.appengine.ext.webapp import template
import os
import math
import string
import random
from config import APP_KEY_COUNT_LIMIT
from api import WriteJson, AppKey, AccessToken, get_current_item
from api.myoauth import OAuthError
from location import members_in_memery
from google.appengine.api.datastore_types import GeoPt

class AccessTokenReqeust(BaseOauthRequest):
    oauth_consumer_key = None
    oauth_consumer_secret = None
    oauth_signature = None
    x_auth_username = ""
    x_auth_password = ""

    def post(self):
        try:
            self.readOauthHeader()
            self.verify_oauth()
            self.requestHandler()
        except OAuthError, err:
            self.send_error(200,err.message)

    def requestHandler(self):
        x_auth_username = self.parameters['x_auth_username']
        x_auth_password = self.parameters['x_auth_password']
        member = Member.verify_user(self, x_auth_username, x_auth_password)
        if member is False:
            self.send_error(401, language.username_or_password_err)
            return
        access_token = self.generate_access_token()
        access_token_secret = self.generate_access_token_secret()
        token = AccessToken(access_token_key=access_token,access_token_secret=access_token_secret,token_owner=member)
        token.put()
        memcache.set('AccessToken::' + access_token, token, 86400)
        data = {}
        data['access_token'] = access_token
        data['access_token_secret'] = access_token_secret
        data['one'] = member
        p = db.GqlQuery('SELECT * FROM Location WHERE member = :1',member)[0].location
        data['location'] = str(p.lat)+","+str(p.lon)
        data['current_item'] = memcache.get("PassByItem::"+str(member.key().id))
        WriteJson(self,data,"signin.json")
        
    def verify_oauth(self):
        app_key = AppKey.verify_app_key(self.parameters['oauth_consumer_key'])
        if app_key is False:
            raise OAuthError("Invalid Consumer Key %s" % self.parameters['oauth_consumer_key'])
        self.oauth_consumer_key = app_key.app_key
        self.oauth_consumer_secret = app_key.app_secret
        signature_method = None
        if self.parameters['oauth_signature_method']:
            if self.parameters['oauth_signature_method'] == HMAC_SHA1:
                signature_method = OAuthSignatureMethod_HMAC_SHA1()
            elif self.parameters['oauth_signature_method'] == PLAINTEXT:
                signature_method = OAuthSignatureMethod_PLAINTEXT()
            else:
                raise OAuthError('Invalid signatrue method')
        oauth_signature = self.parameters['oauth_signature']
        signatrue = signature_method.build_signature(oauth_request=self,consumer=app_key,token=None)
        self.parameters['oauth_signature'] = oauth_signature
        if signatrue != oauth_signature:
            raise OAuthError("Invalid signatrue")
        
    def generate_access_token(self):
        return string.join(random.sample("a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9".split("|"), 15)).replace(" ","")
    
    def generate_access_token_secret(self):
        return string.join(random.sample("a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9".split("|"), 20)).replace(" ","")
    
class BaseSourceOauthRequest(BaseOauthRequest):
    def get(self):
        try:
            self.readOauthHeader()
            self.verify_oauth()
            member = get_member_by_access_token(self.parameters['access_token'])
            self.getHandler(member)
        except OAuthError, err:
            self.response.out.write(err.message)
            
    def post(self):
        try:
            self.readOauthHeader()
            self.verify_oauth()
            member = get_member_by_access_token(self.parameters['oauth_token'])
            self.postHandler(member)
        except OAuthError, err:
            self.response.out.write(err.message)
            
    def verify_oauth(self):
        app_key = AppKey.verify_app_key(self.parameters['oauth_consumer_key'])
        if app_key is False:
            raise OAuthError("Invalid Consumer Key %s" % self.parameters['oauth_consumer_key'])
        access_token = AccessToken.verify_access_token(self.parameters['oauth_token'])
        if access_token is False:
            raise OAuthError("Invalid access_token %s" % self.parameters['oauth_token'])
        signature_method = None
        if self.parameters['oauth_signature_method']:
            if self.parameters['oauth_signature_method'] == HMAC_SHA1:
                signature_method = OAuthSignatureMethod_HMAC_SHA1()
            elif self.parameters['oauth_signature_method'] == PLAINTEXT:
                signature_method = OAuthSignatureMethod_PLAINTEXT()
            else:
                raise OAuthError('Invalid signatrue method')
        oauth_signature = self.parameters['oauth_signature']
        signatrue = signature_method.build_signature(oauth_request=self,consumer=app_key,token=access_token)
        if signatrue != oauth_signature:
            raise OAuthError("Invalid signatrue")
            
    def getHandler(self,member):
        raise NotImplementedError()
    
    def postHandler(self,member):
        raise NotImplementedError()

class OAuthSignin(BaseSourceOauthRequest):
    def postHandler(self,member):
        data = {}
        data['one'] = member
        p = db.GqlQuery('SELECT * FROM Location WHERE member = :1',member)[0].location
        data['location'] = str(p.lat)+","+str(p.lon)
        data['current_item'] = get_current_item(member)
        WriteJson(self,data,"signin.json")
        
class Signout(BaseSourceOauthRequest):
    def postHandler(self,member):
        access_token = self.parameters['oauth_token']
        memcache.delete('AccessToken::' + str(access_token))
        q = db.GqlQuery('SELECT * FROM AccessToken WHERE access_token_key = :1', access_token)
        if q.count() == 1:
            q[0].delete()
        data = {'result':'true',
                'message':'登出成功'}
        WriteJson(self, data, 'normalResult.json')
        

class AppKeyRequest(RequestHandler):
    def get(self):
        member = get_current_member(self)
        if member:
            path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'static', 'html', 'app_key_request.html')
            data = {}
            output = template.render(path,data)
            self.response.out.write(output)
        else:
            self.redirect('/signin?dest='+self.request.path)
            
    def post(self):
        member = get_current_member(self)
        if member:
            q = db.GqlQuery("SELECT __key__ FROM AppKey WHERE app_owner = :1",member)
            if q.count() >= APP_KEY_COUNT_LIMIT:
                #TODO
                self.response.out.write("您申请的应用程序已达上限")
                return
            app_name = self.request.get("app_name")
            app_description = self.request.get("app_description")
            if self.verify_app(app_name,app_description):
                key = self.generate_app_key()
                q = db.GqlQuery("SELECT __key__ FROM AppKey WHERE app_key = :1",key)
                while q.count() >= 1:
                    key = self.generate_app_key()
                    q = db.GqlQuery("SELECT __key__ FROM App_Key WHERE app_key = :1",key)
                app_key = AppKey(app_key=key)
                app_key.app_secret = self.generate_app_secret()
                app_key.app_owner = member
                app_key.app_name = app_name
                app_key.app_description = app_description
                app_key.has_checked = True#TODO 设置审核页面
                app_key.put()
                data = {}
                data["app_name"] = app_name
                data["app_description"] = app_description
                data["app_key"] = app_key.app_key
                data["app_secret"] = app_key.app_secret
                path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'static', 'html', 'app_key_success.html')
                out = template.render(path,data)
                self.response.out.write(out)
            else:
                path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'static', 'html', 'app_key_request.html')
                data = {}
                data["app_name"] = app_name
                data["app_description"] = app_description
                output = template.render(path,data)
                self.response.out.write(output)
        else:
            self.redirect('/signin?dest='+self.request.url)
        
    def generate_app_key(self):
        return string.join(random.sample("a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9".split("|"), 9)).replace(" ","")
    
    def generate_app_secret(self):
        return string.join(random.sample("a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9".split("|"), 12)).replace(" ","")
    
    def verify_app(self,app_name,app_key):
        return True

def main():
    application = webapp.WSGIApplication([('/oauth/access_token',AccessTokenReqeust),
                                          ('/oauth/oauth_signin',OAuthSignin),
                                          ('/oauth/app_key',AppKeyRequest),
                                          ('/oauth/signout',Signout)
                                          ],
                                         debug=True)
    util.run_wsgi_app(application)
    
if __name__ == '__main__':
    main()